package cn.jiemusic.utils;

import org.springframework.core.io.Resource;

import java.io.*;
import java.net.URI;
import java.net.URL;

/**
 * 分段读取文件的 Resource 实现
 */
public class RangeResource implements Resource {
    private final Resource delegate;
    private final long start;
    private final long end;

    public RangeResource(Resource delegate, long start, long end) throws IOException {
        if (start < 0 || end < start) {
            throw new IllegalArgumentException("Invalid range: start must be >= 0 and end must be >= start.");
        }
        this.delegate = delegate;
        if (!delegate.exists()) {
            throw new FileNotFoundException("Resource does not exist: " + delegate.getDescription());
        }
        long contentLength = delegate.contentLength();
        if (end >= contentLength) {
            throw new IllegalArgumentException("End position exceeds resource content length.");
        }
        this.start = start;
        this.end = end;
    }

    @Override
    public boolean exists() {
        return delegate.exists();
    }

    @Override
    public long contentLength() {
        return end - start + 1;
    }

    @Override
    public String getFilename() {
        return delegate.getFilename();
    }

    @Override
    public InputStream getInputStream() throws IOException {
        InputStream inputStream = delegate.getInputStream();
        try {
            if (inputStream.skip(start) != start) {
                throw new IOException("Failed to skip to the start position.");
            }
            return new BufferedInputStream(new LimitedInputStream(inputStream, contentLength()));
        } catch (IOException ex) {
            inputStream.close();
            throw ex;
        }
    }

    @Override
    public URI getURI() throws IOException {
        return delegate.getURI();
    }

    @Override
    public File getFile() throws IOException {
        return delegate.getFile();
    }

    @Override
    public URL getURL() throws IOException {
        return delegate.getURL();
    }

    @Override
    public boolean isReadable() {
        return delegate.isReadable();
    }

    @Override
    public boolean isOpen() {
        return delegate.isOpen();
    }

    @Override
    public boolean isFile() {
        return delegate.isFile();
    }

    @Override
    public Resource createRelative(String relativePath) throws IOException {
        return delegate.createRelative(relativePath);
    }

    @Override
    public String getDescription() {
        return delegate.getDescription();
    }

    @Override
    public long lastModified() throws IOException {
        return delegate.lastModified();
    }

    /**
     * 内部类：限制读取的 InputStream
     */
    private static class LimitedInputStream extends FilterInputStream {
        private long remaining;

        protected LimitedInputStream(InputStream in, long limit) {
            super(in);
            this.remaining = limit;
        }

        @Override
        public int read() throws IOException {
            if (remaining <= 0) return -1;
            int result = super.read();
            if (result != -1) remaining--;
            return result;
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            if (remaining <= 0) return -1;
            len = (int) Math.min(len, remaining);
            int count = super.read(b, off, len);
            if (count != -1) remaining -= count;
            return count;
        }
    }
}
